/**entity factory
 * a cross-api interface for instanciating entities with
 * definitions in lua code
 */

#ifndef ENTITY_FACTORY_H
#define ENTITY_FACTORY_H

#include "lua.hpp"
#include <stack>
#include <vector>
#include "vector.hpp"
#include "entity.h"

namespace engine {

  //Function that registers the C routines to functions in lua, so the
  //C functions can be called from within lua
  void register_functions(lua_State *L);

  class shared_entity_factory
  {
  public:
    /** Creates an instance of an entity of the given class name
     * the definition of this class should be somewhere in the prototype
     * library, with a definition in lua.
     * Entity is spawned at position p with direction d. This takes no id argument, so it
     * should only ever be called on the server
     * @RETURN returns identifier for the created object, -1 on error
     */
    static int Create(lua_State *L, const char* classname,
                      const fixedpoint::vec2d& p, const fixedpoint::vec2d& d
                      );

    /** Creates an instance of an entity of the given class name
     * the definition of this class should be somewhere in the prototype
     * library, with a definition in lua.
     * Entity is spawned at position p with direction d. This takes an id argument
     * that should be determined from the server. As such, this function
     * should only ever be called on the client
     * @RETURN returns identifier for the created object, -1 on error
     */
    static int Create(lua_State *L, const char* classname,
                      const fixedpoint::vec2d& p, const fixedpoint::vec2d& d,
                      unsigned int id);

    /** Destroys the object of the indicated id
     * @NOTE: This is a dangerous function, and should only
     * be called at specific syncronization points. Most of the
     * time you should be calling 'MarkForDestruction'
     */
    static int Destroy(lua_State *L, unsigned int id);

    /** Marks the indicated entity (by id) for deletion upon
     * arrival at the next syncronization point. While the
     * entity is considered dead at this point, it's resources
     * may still exist and may execute one or more 'think' routines
     * before it's actual destruction and garbage collection. May be
     * called at any time
     */
    static void MarkForDestruction(lua_State *L, unsigned int id);

  private:
    /** These functions are similar to the above functions
     * but they should only be called from lua
     */
    static int Create(lua_State *L);
    static int MarkForDestruction(lua_State *L);
    static int Destroy(lua_State *L);

    //Only register function can access these
    friend void register_functions(lua_State *L);
  };

  class client_entity_factory
  {
  public:
    /** Creates an instance of an entity of the given class name
     * the definition of this class should be somewhere in the prototype
     * library, with a definition in lua.
     * @RETURN returns identifier for the created object, -1 on error
     */
    static int Create(lua_State *L, const char* classname);

    /** Destroys the object of the indicated id
     * @NOTE: This is a dangerous function, and should only
     * be called at specific syncronization points. Most of the
     * time you should be calling 'MarkForDestruction'
     */
    static int Destroy(lua_State *L, unsigned int id);

    /** Marks the indicated entity (by id) for deletion upon
     * arrival at the next syncronization point. While the
     * entity is considered dead at this point, it's resources
     * may still exist and may execute one or more 'think' routines
     * before it's actual destruction and garbage collection. May be
     * called at any time
     */
    static void MarkForDestruction(lua_State *L, unsigned int id);

  private:
  };

}

#endif
